home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / C / Games / NetHack 3.1.3 / source / src / end.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-08-01  |  19.7 KB  |  828 lines  |  [TEXT/R*ch]

  1. /*    SCCS Id: @(#)end.c    3.1    93/06/30    */
  2. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  3. /* NetHack may be freely redistributed.  See license for details. */
  4.  
  5. #define NEED_VARARGS    /* comment line for pre-compiled headers */
  6.  
  7. #include "hack.h"
  8. #include "eshk.h"
  9. #ifndef NO_SIGNAL
  10. #include <signal.h>
  11. #endif
  12.  
  13.  
  14. STATIC_PTR int NDECL(done_intr);
  15. static void FDECL(disclose,(int,BOOLEAN_P));
  16. static struct obj *FDECL(get_valuables, (struct obj *));
  17. static void FDECL(savelife, (int));
  18. static void NDECL(list_vanquished);
  19. static void NDECL(list_genocided);
  20.  
  21. #ifdef AMIGA
  22. void NDECL(clear_icon);
  23. #endif
  24.  
  25. /*
  26.  * The order of these needs to match the macros in hack.h.
  27.  */
  28. static NEARDATA const char *deaths[] = {        /* the array of death */
  29.     "died", "choked", "poisoned", "starvation", "drowning",
  30.     "burning", "crushed", "turned to stone", "genocided",
  31.     "panic", "trickery",
  32.     "quit", "escaped", "ascended"
  33. };
  34.  
  35. static NEARDATA const char *ends[] = {        /* "when you..." */
  36.     "died", "choked", "were poisoned", "starved", "drowned",
  37.     "burned", "were crushed", "turned to stone", "were genocided",
  38.     "panicked", "were tricked",
  39.     "quit", "escaped", "ascended"
  40. };
  41.  
  42. int
  43. done1()
  44. {
  45. #ifndef NO_SIGNAL
  46.     (void) signal(SIGINT,SIG_IGN);
  47. #endif
  48.     if(flags.ignintr) {
  49. #ifndef NO_SIGNAL
  50.         (void) signal(SIGINT, (SIG_RET_TYPE) done1);
  51. #endif
  52.         clear_nhwindow(WIN_MESSAGE);
  53.         curs_on_u();
  54.         wait_synch();
  55.         if(multi > 0) nomul(0);
  56.         return 0;
  57.     }
  58.     return done2();
  59. }
  60.  
  61. int
  62. done2()
  63. {
  64.     if(yn("Really quit?") == 'n') {
  65. #ifndef NO_SIGNAL
  66.         (void) signal(SIGINT, (SIG_RET_TYPE) done1);
  67. #endif
  68.         clear_nhwindow(WIN_MESSAGE);
  69.         curs_on_u();
  70.         wait_synch();
  71.         if(multi > 0) nomul(0);
  72.         if(multi == 0) {
  73.             u.uinvulnerable = FALSE;    /* avoid ctrl-C bug -dlc */
  74.             u.usleep = 0;
  75.         }
  76.         return 0;
  77.     }
  78. #if defined(WIZARD) && (defined(UNIX) || defined(VMS) || defined(LATTICE))
  79.     if(wizard) {
  80.         int c;
  81. # ifdef VMS
  82.         const char *tmp = "Enter debugger?";
  83. # else
  84. #  ifdef LATTICE
  85.         const char *tmp = "Create SnapShot?";
  86. #  else
  87.         const char *tmp = "Dump core?";
  88. #  endif
  89. # endif
  90.         if ((c = ynq(tmp)) == 'y') {
  91.         (void) signal(SIGINT, (SIG_RET_TYPE) done1);
  92.         exit_nhwindows(NULL);
  93. #ifdef AMIGA
  94.         Abort(0);
  95. #else
  96. # ifdef SYSV
  97.         (void)
  98. # endif
  99.             abort();
  100. #endif
  101.         } else if (c == 'q') done_stopprint++;
  102.     }
  103. #endif
  104. #ifndef LINT
  105.     done(QUIT);
  106. #endif
  107.     return 0;
  108. }
  109.  
  110. STATIC_PTR
  111. int
  112. done_intr()
  113. {
  114.     done_stopprint++;
  115. #ifndef NO_SIGNAL
  116.     (void) signal(SIGINT, SIG_IGN);
  117. # if defined(UNIX) || defined(VMS)
  118.     (void) signal(SIGQUIT, SIG_IGN);
  119. # endif
  120. #endif /* NO_SIGNAL */
  121.     return 0;
  122. }
  123.  
  124. #if defined(UNIX) || defined(VMS)
  125. static
  126. int
  127. done_hangup()
  128. {
  129.     done_hup++;
  130.     (void)signal(SIGHUP, SIG_IGN);
  131.     (void)done_intr();
  132.     return 0;
  133. }
  134. #endif
  135.  
  136. void
  137. done_in_by(mtmp)
  138. register struct monst *mtmp;
  139. {
  140.     char buf[BUFSZ];
  141.  
  142.     You("die...");
  143.     mark_synch();    /* flush buffered screen output */
  144.     buf[0] = '\0';
  145.     if (type_is_pname(mtmp->data) || (mtmp->data->geno & G_UNIQ)) {
  146.          if (!(type_is_pname(mtmp->data) && (mtmp->data->geno & G_UNIQ)))
  147.         Strcat(buf, "the ");
  148.          killer_format = KILLED_BY;
  149.     }
  150.     if (mtmp->minvis)
  151.         Strcat(buf, "invisible ");
  152.     if (Hallucination)
  153.         Strcat(buf, "hallucinogen-distorted ");
  154.  
  155.     if(mtmp->data == &mons[PM_GHOST]) {
  156.         register char *gn = (char *) mtmp->mextra;
  157.         if (!Hallucination && !mtmp->minvis && *gn) {
  158.             Strcat(buf, "the ");
  159.             killer_format = KILLED_BY;
  160.         }
  161.         Sprintf(eos(buf), (*gn ? "ghost of %s" : "ghost%s"), gn);
  162.     } else if(mtmp->isshk) {
  163.         Sprintf(eos(buf), "%s %s, the shopkeeper",
  164.             (mtmp->female ? "Ms." : "Mr."), shkname(mtmp));
  165.         killer_format = KILLED_BY;
  166.     } else if (mtmp->ispriest || mtmp->isminion) {
  167.         killer = priestname(mtmp);
  168.         if (!strncmp(killer, "the ", 4)) Strcat(buf, killer+4);
  169.         else Strcat(buf, killer);
  170.     } else Strcat(buf, mtmp->data->mname);
  171.     if (mtmp->mnamelth) Sprintf(eos(buf), " called %s", NAME(mtmp));
  172.     killer = buf;
  173.     if (mtmp->data->mlet == S_WRAITH)
  174.         u.ugrave_arise = PM_WRAITH;
  175.     else if (mtmp->data->mlet == S_MUMMY)
  176.         u.ugrave_arise = (pl_character[0]=='E') ?
  177.                         PM_ELF_MUMMY : PM_HUMAN_MUMMY;
  178.     else if (mtmp->data->mlet == S_VAMPIRE)
  179.         u.ugrave_arise = PM_VAMPIRE;
  180.     if (u.ugrave_arise > -1 && (mons[u.ugrave_arise].geno & G_GENOD))
  181.         u.ugrave_arise = -1;
  182.     if (mtmp->data->mlet == S_COCKATRICE)
  183.         done(STONING);
  184.     else
  185.         done(DIED);
  186.     return;
  187. }
  188.  
  189. /*VARARGS1*/
  190. boolean panicking;
  191. extern boolean hu;    /* from save.c */
  192.  
  193. void
  194. panic VA_DECL(const char *, str)
  195.     VA_START(str);
  196.     VA_INIT(str, char *);
  197.  
  198.     if(panicking++)
  199. #ifdef AMIGA
  200.         Abort(0);
  201. #else
  202. # ifdef SYSV
  203.         (void)
  204. # endif
  205.         abort();    /* avoid loops - this should never happen*/
  206. #endif
  207.  
  208.     if (flags.window_inited) exit_nhwindows(NULL);
  209.     flags.window_inited = 0; /* they're gone; force raw_print()ing */
  210.  
  211.     raw_print(" Suddenly, the dungeon collapses.");
  212. #if defined(WIZARD) && !defined(MICRO)
  213.     if(!wizard) {
  214.         raw_printf("Report error to %s and it may be possible to rebuild.",
  215. # ifdef WIZARD_NAME    /*(KR1ED)*/
  216.         WIZARD_NAME);
  217. # else
  218.         WIZARD);
  219. # endif
  220.     }
  221.     set_error_savefile();
  222.     hu = FALSE;
  223.     (void) dosave0();
  224. #endif
  225.     {
  226.         char buf[BUFSZ];
  227.         Vsprintf(buf,str,VA_ARGS);
  228.         raw_print(buf);
  229.     }
  230. #if defined(WIZARD) && (defined(UNIX) || defined(VMS) || defined(LATTICE))
  231.     if (wizard)
  232. # ifdef AMIGA
  233.         Abort(0);
  234. # else
  235. #  ifdef SYSV
  236.         (void)
  237. #  endif
  238.             abort();    /* generate core dump */
  239. # endif
  240. #endif
  241.     VA_END();
  242.     done(PANICKED);
  243. }
  244.  
  245. static void
  246. disclose(how,taken)
  247. int how;
  248. boolean taken;
  249. {
  250.     char    c;
  251.     char    qbuf[QBUFSZ];
  252.  
  253.     if (invent && !done_stopprint &&
  254.         (!flags.end_disclose[0] || index(flags.end_disclose, 'i'))) {
  255.         if(taken)
  256.         Sprintf(qbuf,"Do you want to see what you had when you %s?",
  257.             (how == QUIT) ? "quit" : "died");
  258.         else
  259.         Strcpy(qbuf,"Do you want your possessions identified?");
  260.         if ((c = yn_function(qbuf, ynqchars, 'y')) == 'y') {
  261.         /* New dump format by maartenj@cs.vu.nl */
  262.         struct obj *obj;
  263.  
  264.         for(obj = invent; obj && !done_stopprint; obj = obj->nobj) {
  265.             makeknown(obj->otyp);
  266.             obj->known = obj->bknown = obj->dknown = obj->rknown = 1;
  267.         }
  268.         (void) display_inventory(NULL, FALSE);
  269.         container_contents(invent, TRUE, TRUE);
  270.         }
  271.         if (c == 'q')  done_stopprint++;
  272.         if (taken) {
  273.         /* paybill has already given the inventory locations
  274.          * in the shop and put it on the main object list
  275.          */
  276.         struct obj *obj;
  277.  
  278.         for(obj = invent; obj; obj = obj->nobj) {
  279.             obj->owornmask = 0;
  280.             if(rn2(5)) curse(obj);
  281.         }
  282.         invent = (struct obj *) 0;
  283.         }
  284.     }
  285.  
  286.     if (!done_stopprint &&
  287.         (!flags.end_disclose[0] || index(flags.end_disclose, 'a'))) {
  288.         c = yn_function("Do you want to see your attributes?",ynqchars,'y');
  289.         if (c == 'y') enlightenment(TRUE);    /* final */
  290.         if (c == 'q') done_stopprint++;
  291.     }
  292.  
  293.     if (!done_stopprint &&
  294.         (!flags.end_disclose[0] || index(flags.end_disclose, 'v'))) {
  295.         list_vanquished();
  296.     }
  297.  
  298.     if (!done_stopprint &&
  299.         (!flags.end_disclose[0] || index(flags.end_disclose, 'g'))) {
  300.         list_genocided();
  301.     }
  302. }
  303.  
  304. /* try to get the player back in a viable state after being killed */
  305. static void
  306. savelife(how)
  307. int how;
  308. {
  309.     u.uswldtim = 0;
  310.     u.uhp = u.uhpmax;
  311.     if (u.uhunger < 500) {
  312.         u.uhunger = 500;
  313.         newuhs(FALSE);
  314.     }
  315.     if (how == CHOKING) init_uhunger();
  316.     nomovemsg = "You survived that attempt on your life.";
  317.     flags.move = 0;
  318.     if(multi > 0) multi = 0; else multi = -1;
  319.     if(u.utrap && u.utraptype == TT_LAVA) u.utrap = 0;
  320.     flags.botl = 1;
  321.     u.ugrave_arise = -1;
  322.     curs_on_u();
  323. }
  324.  
  325. /*
  326.  *  Get valuables from the given list. NOTE: The list is destroyed as it is
  327.  *  processed, so don't expect to use it again!
  328.  */
  329. static struct obj *
  330. get_valuables(list)
  331.     struct obj *list;
  332. {
  333.     struct obj *obj, *next_obj, *c_vals, *temp;
  334.     struct obj *valuables = (struct obj *)0;
  335.  
  336.     for (obj = list; obj; obj = next_obj) {
  337.     if (Has_contents(obj)) {
  338.         c_vals = get_valuables(obj->cobj);
  339.  
  340.         if (c_vals) {
  341.         /* find the end of the list */
  342.         for (temp = c_vals; temp->nobj; temp = temp->nobj) ;
  343.  
  344.         temp->nobj = valuables;
  345.         valuables = c_vals;
  346.         }
  347.     }
  348.  
  349.     next_obj = obj->nobj;
  350.  
  351.     if ((obj->oclass == GEM_CLASS && obj->otyp < LUCKSTONE)
  352.         || obj->oclass == AMULET_CLASS) {
  353.         obj->nobj = valuables;
  354.         valuables = obj;
  355.     }
  356.     }
  357.     return valuables;
  358. }
  359.  
  360. /* Be careful not to call panic from here! */
  361. void
  362. done(how)
  363. int how;
  364. {
  365.     struct permonst *upmon;
  366.     boolean taken;
  367.     char kilbuf[BUFSZ], pbuf[BUFSZ];
  368.     winid endwin = WIN_ERR;
  369.     boolean have_windows = flags.window_inited;
  370.  
  371.     /* kilbuf: used to copy killer in case it comes from something like
  372.      *    xname(), which would otherwise get overwritten when we call
  373.      *    xname() when listing possessions
  374.      * pbuf: holds Sprintf'd output for raw_print and putstr
  375.      */
  376.     if (how == ASCENDED)
  377.         killer_format = NO_KILLER_PREFIX;
  378.     /* Avoid killed by "a" burning or "a" starvation */
  379.     if (!killer && (how == STARVING || how == BURNING))
  380.         killer_format = KILLED_BY;
  381.     Strcpy(kilbuf, (!killer || how >= PANICKED ? deaths[how] : killer));
  382.     killer = kilbuf;
  383. #ifdef WIZARD
  384.     if (wizard && how == TRICKED) {
  385.         You("are a very tricky wizard, it seems.");
  386.         return;
  387.     }
  388. #endif
  389.     if (how < PANICKED) u.umortality++;
  390.     if (Lifesaved && how <= GENOCIDED) {
  391.         pline("But wait...");
  392.         makeknown(AMULET_OF_LIFE_SAVING);
  393.         Your("medallion %s!",
  394.               !Blind ? "begins to glow" : "feels warm");
  395.         if (how == CHOKING) You("vomit ...");
  396.         You("feel much better!");
  397.         pline("The medallion crumbles to dust!");
  398.         useup(uamul);
  399.  
  400.         (void) adjattrib(A_CON, -1, TRUE);
  401.         if(u.uhpmax <= 0) u.uhpmax = 10;    /* arbitrary */
  402.         savelife(how);
  403.         if (how == GENOCIDED)
  404.             pline("Unfortunately you are still genocided...");
  405.         else {
  406.             killer = 0;
  407.             return;
  408.         }
  409.     }
  410. #if defined(WIZARD) || defined(EXPLORE_MODE)
  411.     if ((wizard || discover) && how <= GENOCIDED) {
  412.         if(yn("Die?") == 'y') goto die;
  413.         pline("OK, so you don't %s.",
  414.             (how == CHOKING) ? "choke" : "die");
  415.         if(u.uhpmax <= 0) u.uhpmax = u.ulevel * 8;    /* arbitrary */
  416.         savelife(how);
  417.         killer = 0;
  418.         return;
  419.     }
  420. #endif /* WIZARD || EXPLORE_MODE */
  421.     /* Sometimes you die on the first move.  Life's not fair.
  422.      * On those rare occasions you get hosed immediately, go out
  423.      * smiling... :-)  -3.
  424.      */
  425.     if (moves <= 1 && how < PANICKED)
  426.         /* You die... --More-- */
  427.         pline("Do not pass go.  Do not collect 200 zorkmids.");
  428.  
  429. die:
  430.     if (have_windows) wait_synch();    /* flush screen output */
  431. #ifndef NO_SIGNAL
  432.     (void) signal(SIGINT, (SIG_RET_TYPE) done_intr);
  433. # if defined(UNIX) || defined(VMS)
  434.     (void) signal(SIGQUIT, (SIG_RET_TYPE) done_intr);
  435.     (void) signal(SIGHUP, (SIG_RET_TYPE) done_hangup);
  436. # endif
  437. #endif /* NO_SIGNAL */
  438. #ifdef POLYSELF
  439.     if (u.mtimedone)
  440.         upmon = uasmon;
  441.     else
  442. #endif
  443.     upmon = player_mon();
  444.  
  445.     if (u.ugrave_arise < 0) { /* >= 0 means create no corpse */
  446.         if (how == STONING)
  447.         u.ugrave_arise = -2;
  448.  
  449. /*
  450.  * If you're burned to a crisp, why leave a corpse?
  451.  */
  452.         else if (how != BURNING && how != PANICKED)
  453.         (void) mk_named_object(CORPSE, upmon, u.ux, u.uy, plname,
  454.                             (int)strlen(plname));
  455.     }
  456.  
  457.     if (how == QUIT) {
  458.         killer_format = NO_KILLER_PREFIX;
  459.         if (u.uhp < 1) {
  460.             how = DIED;
  461. /* note that killer is pointing at kilbuf */
  462.             Strcpy(kilbuf, "quit while already on Charon's boat");
  463.         }
  464.     }
  465.     if (how == ESCAPED || how == PANICKED)
  466.         killer_format = NO_KILLER_PREFIX;
  467.  
  468.     /* paybill() must be called unconditionally, or strange things will
  469.      * happen to bones levels */
  470.     taken = paybill(how != QUIT);
  471.     paygd();
  472.     clearpriests();
  473.     clearlocks();
  474. #ifdef AMIGA
  475.     clear_icon();
  476. #endif
  477.     if (have_windows) display_nhwindow(WIN_MESSAGE, FALSE);
  478.  
  479.     if (strcmp(flags.end_disclose, "none") && how != PANICKED)
  480.         disclose(how, taken);
  481.  
  482.     if (how < GENOCIDED) {
  483. #ifdef WIZARD
  484.         if (!wizard || yn("Save bones?") == 'y')
  485. #endif
  486.         savebones();
  487.     }
  488.  
  489.     /* calculate score */
  490.     {
  491.         long tmp;
  492.         int deepest = deepest_lev_reached(FALSE);
  493.  
  494.         u.ugold += hidden_gold();    /* accumulate gold from containers */
  495.         tmp = u.ugold - u.ugold0;
  496.         if (tmp < 0L)
  497.         tmp = 0L;
  498.         if (how < PANICKED)
  499.         tmp -= tmp / 10L;
  500.         u.urexp += tmp;
  501.         u.urexp += 50L * (long)(deepest - 1);
  502.         if (deepest > 20)
  503.         u.urexp += 1000L * (long)((deepest > 30) ? 10 : deepest - 20);
  504.         if (how == ASCENDED) u.urexp *= 2L;
  505.     }
  506.  
  507.     /* clean up unneeded windows */
  508.     if (have_windows) {
  509.         destroy_nhwindow(WIN_MAP);
  510.         destroy_nhwindow(WIN_STATUS);
  511.         destroy_nhwindow(WIN_MESSAGE);
  512.  
  513.         if(!done_stopprint || flags.tombstone)
  514.         endwin = create_nhwindow(NHW_TEXT);
  515.  
  516.         if(how < GENOCIDED && flags.tombstone) outrip(endwin, how);
  517.     } else
  518.         done_stopprint = 1; /* just avoid any more output */
  519.  
  520. /* changing kilbuf really changes killer. we do it this way because
  521.    killer is declared a (const char *)
  522. */
  523.     if (u.uhave.amulet) Strcat(kilbuf, " (with the Amulet)");
  524.     if (!done_stopprint) {
  525.         Sprintf(pbuf, "%s %s the %s...",
  526.            (pl_character[0] == 'S') ? "Sayonara" :
  527.            (pl_character[0] == 'T') ? "Aloha" : "Goodbye", plname,
  528.            how != ASCENDED ? (const char *) pl_character :
  529.            (const char *) (flags.female ? "Demigoddess" : "Demigod"));
  530.         putstr(endwin, 0, pbuf);
  531.         putstr(endwin, 0, "");
  532.     }
  533.     if (how == ESCAPED || how == ASCENDED) {
  534.         register struct monst *mtmp;
  535.         register struct obj *otmp;
  536.         struct obj *jewels;
  537.         long i;
  538.         register long worthlessct = 0;
  539.  
  540.         /*
  541.          *  Put items that count into the jewels chain.  Rewriting
  542.          *  the invent chain and all the container chains (within
  543.          *  invent) here is safe.  They will never be used again.
  544.          */
  545.         jewels = get_valuables(invent);
  546.  
  547.         /* add points for jewels */
  548.         for(otmp = jewels; otmp; otmp = otmp->nobj) {
  549.             if(otmp->oclass == GEM_CLASS)
  550.                 u.urexp += otmp->quan *
  551.                         objects[otmp->otyp].oc_cost;
  552.             else    /* amulet */
  553.                 u.urexp += objects[otmp->otyp].oc_cost;
  554.         }
  555.  
  556.         keepdogs();
  557.         viz_array[0][0] |= IN_SIGHT; /* need visibility for naming */
  558.         mtmp = mydogs;
  559.         if(!done_stopprint) Strcpy(pbuf, "You");
  560.         if(mtmp) {
  561.             while(mtmp) {
  562.                 if(!done_stopprint) {
  563.                     Strcat(pbuf, " and ");
  564.                     Strcat(pbuf, mon_nam(mtmp));
  565.                 }
  566.                 if(mtmp->mtame)
  567.                     u.urexp += mtmp->mhp;
  568.                 mtmp = mtmp->nmon;
  569.             }
  570.             if(!done_stopprint)
  571.                 putstr(endwin, 0, pbuf);
  572.             pbuf[0] = 0;
  573.         } else {
  574.             if(!done_stopprint)
  575.                 Strcat(pbuf, " ");
  576.         }
  577.         if(!done_stopprint) {
  578.             Sprintf(eos(pbuf),
  579.                 "%s with %ld point%s,",
  580.                 how==ASCENDED ? "went to your reward"
  581.                 : "escaped from the dungeon",
  582.                 u.urexp, plur(u.urexp));
  583.             putstr(endwin, 0, pbuf);
  584.         }
  585.  
  586.         /* print jewels chain here */
  587.         for(otmp = jewels; otmp; otmp = otmp->nobj) {
  588.             makeknown(otmp->otyp);
  589.             if(otmp->oclass == GEM_CLASS &&
  590.                otmp->otyp < LUCKSTONE) {
  591.                 i = otmp->quan *
  592.                     objects[otmp->otyp].oc_cost;
  593.                 if(i == 0) {
  594.                     worthlessct += otmp->quan;
  595.                     continue;
  596.                 }
  597.             } else {        /* amulet */
  598.                 otmp->known = 1;
  599.                 i = objects[otmp->otyp].oc_cost;
  600.             }
  601.             if(!done_stopprint) {
  602.                 Sprintf(pbuf, "        %s (worth %ld zorkmids),",
  603.                     doname(otmp), i);
  604.                 putstr(endwin, 0, pbuf);
  605.             }
  606.         }
  607.         if(worthlessct && !done_stopprint) {
  608.             Sprintf(pbuf,
  609.               "        %ld worthless piece%s of colored glass,",
  610.               worthlessct, plur(worthlessct));
  611.             putstr(endwin, 0, pbuf);
  612.         }
  613.     } else if (!done_stopprint) {
  614.         Strcpy(pbuf, "You ");
  615.         Strcat(pbuf, ends[how]);
  616.         if (how != ASCENDED) {
  617.             Strcat(pbuf, " in ");
  618.             if (Is_astralevel(&u.uz))
  619.             Strcat(pbuf, "The Astral Plane");
  620.             else Strcat(pbuf, dungeons[u.uz.dnum].dname);
  621.             Strcat(pbuf, " ");
  622.             if (!In_endgame(&u.uz)
  623. #ifdef MULDGN
  624.                            && !Is_knox(&u.uz)
  625. #endif
  626.             )
  627.             Sprintf(eos(pbuf), "on dungeon level %d ", (
  628. #ifdef MULDGN
  629.                          In_quest(&u.uz) ?
  630.                             dunlev(&u.uz) :
  631. #endif
  632.                             depth(&u.uz)));
  633.         }
  634.         Sprintf(eos(pbuf),
  635.             "with %ld point%s,", u.urexp, plur(u.urexp));
  636.         putstr(endwin, 0, pbuf);
  637.     }
  638.     if (!done_stopprint) {
  639.         Sprintf(pbuf, "and %ld piece%s of gold, after %ld move%s.",
  640.             u.ugold, plur(u.ugold), moves, plur(moves));
  641.         putstr(endwin, 0, pbuf);
  642.     }
  643.     if (!done_stopprint) {
  644.         Sprintf(pbuf,
  645.          "You were level %u with a maximum of %d hit point%s when you %s.",
  646.             u.ulevel, u.uhpmax, plur(u.uhpmax), ends[how]);
  647.         putstr(endwin, 0, pbuf);
  648.         putstr(endwin, 0, "");
  649.     }
  650.     if (!done_stopprint)
  651.         display_nhwindow(endwin, TRUE);
  652.     if (have_windows)
  653.         exit_nhwindows(NULL);
  654.     /* "So when I die, the first thing I will see in Heaven is a
  655.      * score list?" */
  656.     topten(how);
  657.     if(done_stopprint) { raw_print(""); raw_print(""); }
  658.     terminate(0);
  659. }
  660.  
  661.  
  662. #ifdef NOSAVEONHANGUP
  663. int
  664. hangup()
  665. {
  666.     (void) signal(SIGINT, SIG_IGN);
  667.     clearlocks();
  668. # ifndef VMS
  669.     terminate(1);
  670. # endif
  671. }
  672. #endif
  673.  
  674.  
  675. void
  676. container_contents(list, identified, all_containers)
  677.     struct obj *list;
  678.     boolean identified, all_containers;
  679. {
  680.     register struct obj *box, *obj;
  681.     char buf[BUFSZ];
  682.  
  683.     for (box = list; box; box = box->nobj) {
  684.         if (Is_container(box) && box->otyp != BAG_OF_TRICKS) {
  685.         if (box->cobj) {
  686.             winid tmpwin = create_nhwindow(NHW_MENU);
  687.             Sprintf(buf, "Contents of %s:", the(xname(box)));
  688.             putstr(tmpwin, 0, buf); putstr(tmpwin, 0, "");
  689.             for (obj = box->cobj; obj; obj = obj->nobj) {
  690.             if (identified) {
  691.                 makeknown(obj->otyp);
  692.                 obj->known = obj->bknown =
  693.                 obj->dknown = obj->rknown = 1;
  694.             }
  695.             putstr(tmpwin, 0, doname(obj));
  696.             }
  697.             display_nhwindow(tmpwin, TRUE);
  698.             destroy_nhwindow(tmpwin);
  699.             if (all_containers)
  700.             container_contents(box->cobj, identified, TRUE);
  701.         } else {
  702.             pline("%s is empty.", The(xname(box)));
  703.             display_nhwindow(WIN_MESSAGE, FALSE);
  704.         }
  705.         }
  706.         if (!all_containers)
  707.         break;
  708.     }
  709. }
  710.  
  711.  
  712. void
  713. terminate(status)
  714. int status;
  715. {
  716. #ifdef MAC
  717.     if (!hu) {
  718.         getreturn("to exit");
  719.     }
  720. #endif
  721.     exit(status);
  722. }
  723.  
  724. static void
  725. list_vanquished()
  726. {
  727.     register int i, lev;
  728.     int ntypes = 0, max_lev = 0, nkilled;
  729.     long total_killed = 0L;
  730.     char c;
  731.     static winid klwin;
  732.     char buf[BUFSZ];
  733.  
  734.     /* get totals first */
  735.     for (i = 0; i < NUMMONS; i++) {
  736.     if (u.nr_killed[i]) ntypes++;
  737.     total_killed += (long)u.nr_killed[i];
  738.     if (mons[i].mlevel > max_lev) max_lev = mons[i].mlevel;
  739.     }
  740.  
  741.     /* vanquished foes list;
  742.      * includes all dead monsters, not just those killed by the player
  743.      */
  744.     if (ntypes != 0) {
  745.     c = yn_function("Do you want an account of foes vanquished?",
  746.             ynqchars, 'n');
  747.     if (c == 'q') done_stopprint++;
  748.     if (c == 'y') {
  749.         klwin = create_nhwindow(NHW_MENU);
  750.         putstr(klwin, 0, "Vanquished foes:");
  751.         putstr(klwin, 0, "");
  752.  
  753.         /* countdown by monster "toughness" */
  754.         for (lev = max_lev; lev >= 0; lev--)
  755.           for (i = 0; i < NUMMONS; i++)
  756.         if (mons[i].mlevel == lev && (nkilled = u.nr_killed[i])) {
  757.             if (i == PM_WIZARD_OF_YENDOR || mons[i].geno & G_UNIQ) {
  758.             Sprintf(buf, type_is_pname(&mons[i]) ? mons[i].mname :
  759.                 The(mons[i].mname));
  760.             if (nkilled > 1)
  761.                 Sprintf(eos(buf)," (%d time%s)",
  762.                     nkilled, plur(nkilled));
  763.             } else {
  764.             /* trolls or undead might have come back,
  765.                but we don't keep track of that */
  766.             if (nkilled == 1)
  767.                 Strcpy(buf, an(mons[i].mname));
  768.             else
  769.                 Sprintf(buf, "%d %s",
  770.                     nkilled, makeplural(mons[i].mname));
  771.             }
  772.             putstr(klwin, 0, buf);
  773.         }
  774.         /*
  775.          * if (Hallucination)
  776.          *     putstr(klwin, 0, "and a partridge in a pear tree");
  777.          */
  778.         if (ntypes > 1) {
  779.         putstr(klwin, 0, "");
  780.         Sprintf(buf, "%ld creatures vanquished.", total_killed);
  781.         putstr(klwin, 0, buf);
  782.         }
  783.         display_nhwindow(klwin, TRUE);
  784.         destroy_nhwindow(klwin);
  785.     }
  786.     }
  787. }
  788.  
  789. static void
  790. list_genocided()
  791. {
  792.     register int i;
  793.     int ngenocided = 0;
  794.     char c;
  795.     static winid klwin;
  796.     char buf[BUFSZ];
  797.  
  798.     /* get totals first */
  799.     for (i = 0; i < NUMMONS; i++) {
  800.     if (mons[i].geno & G_GENOD) ngenocided++;
  801.     }
  802.  
  803.     /* genocided species list */
  804.     if (ngenocided != 0) {
  805.     c = yn_function("Do you want a list of species genocided?",
  806.             ynqchars, 'n');
  807.     if (c == 'q') done_stopprint++;
  808.     if (c == 'y') {
  809.         klwin = create_nhwindow(NHW_MENU);
  810.         putstr(klwin, 0, "Genocided species:");
  811.         putstr(klwin, 0, "");
  812.  
  813.         for (i = 0; i < NUMMONS; i++)
  814.         if (mons[i].geno & G_GENOD)
  815.             putstr(klwin, 0, makeplural(mons[i].mname));
  816.  
  817.         putstr(klwin, 0, "");
  818.         Sprintf(buf, "%d species genocided.", ngenocided);
  819.         putstr(klwin, 0, buf);
  820.  
  821.         display_nhwindow(klwin, TRUE);
  822.         destroy_nhwindow(klwin);
  823.     }   
  824.     }
  825. }
  826.  
  827. /*end.c*/
  828.